package com.lagou;

import com.lagou.ann.Service;
import com.lagou.ann.SpringBootApplication;
import com.lagou.handler.UserServiceHandler;
import com.lagou.utils.JSONSerializer;
import com.lagou.utils.RpcDecoder;
import com.lagou.utils.RpcRequest;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringEncoder;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

@SpringBootApplication
public class ServerBoot {


    public static HashMap<String,Object> objectMap = new HashMap<String, Object>();
    private static List<String> classPaths = new ArrayList<String>();

    public static void main(String[] args) throws Exception {
        ServerBoot.run(ServerBootstrap.class, args);
    }


    private static void run(Class<ServerBootstrap> serverBootstrapClass, String[] args) throws Exception {
        // 扫描封装对象
        String classpath = ServerBoot.class.getResource("/").getPath();
        File f = new File(ServerBoot.class.getResource("").getPath());
        doPath(f);
        for (String s : classPaths) {
            s = s.replace(classpath.replace("/", "\\").replaceFirst("\\\\", ""), "").replace("\\", ".").replace(".class", "");
            Class cls = Class.forName(s);
            // 判断注解
            Service serviceannotation = (Service) cls.getAnnotation(Service.class);
            if (serviceannotation != null) {
                Object o = cls.newInstance();
                Class[] interfaces = cls.getInterfaces();
                // 获取接口名称
                String name = interfaces[0].getName();
                objectMap.put(name,o);
            }
        }
        startServer();
    }

    //创建一个方法启动服务器
    public static void startServer() throws InterruptedException {
        //1.创建两个线程池对象
        NioEventLoopGroup bossGroup = new NioEventLoopGroup();
        NioEventLoopGroup  workGroup = new NioEventLoopGroup();

        //2.创建服务端的启动引导对象
        ServerBootstrap serverBootstrap = new ServerBootstrap();

        //3.配置启动引导对象
        serverBootstrap.group(bossGroup,workGroup)
                //设置通道为NIO
                .channel(NioServerSocketChannel.class)
                //创建监听channel
                .childHandler(new ChannelInitializer<NioSocketChannel>() {
                    protected void initChannel(NioSocketChannel nioSocketChannel) throws Exception {
                        //获取管道对象
                        ChannelPipeline pipeline = nioSocketChannel.pipeline();
                        //给管道对象pipeLine 设置编码
                        pipeline.addLast(new StringEncoder());
                        pipeline.addLast(new RpcDecoder(RpcRequest.class, new JSONSerializer()));
                        //把我们自定义一个ChannelHander添加到通道中
                        pipeline.addLast(new UserServiceHandler());
                    }
                });

        //4.绑定端口
        serverBootstrap.bind(8999).sync();
    }

    public static HashMap<String, Object> getObjectMap() {
        return objectMap;
    }

    public static void setObjectMap(HashMap<String, Object> objectMap) {
        ServerBoot.objectMap = objectMap;
    }

    /**
     * 该方法会得到所有的类，将类的绝对路径写入到classPaths中
     *
     * @param file
     */
    private static void doPath(File file) {
        if (file.isDirectory()) {//文件夹
            //文件夹我们就递归
            File[] files = file.listFiles();
            for (File f1 : files) {
                doPath(f1);
            }
        } else {//标准文件
            //标准文件我们就判断是否是class文件
            if (file.getName().endsWith(".class")) {
                //如果是class文件我们就放入我们的集合中。
                classPaths.add(file.getPath());
            }
        }
    }
}
